﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;

namespace FoundationLib.Common.Extensions
{
	/// <summary>
	/// Defines extension methods for <see cref="IQueryable"/> types.
	/// </summary>
	public static class QueryableExtensions
	{
		/// <summary>
		/// Orders the given <see cref="IQueryable{T}"/> source using the given sorting options.
		/// </summary>
		/// <typeparam name="T">The type of the elements in <paramref name="source"/></typeparam>
		/// <param name="source">The data source</param>
		/// <param name="sortingOptions">The sorting options</param>
		/// <returns>The ordered result</returns>
		public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, SortingOptions sortingOptions)
		{
			if (source == null)
				throw new ArgumentNullException("source");
			if (sortingOptions == null)
				throw new ArgumentNullException("sortingOptions");

			MethodCallExpression methodExpression = sortingOptions.MethodCallExpression<T>(source);
			return source.Provider.CreateQuery<T>(methodExpression);
		}

		/// <summary>
		/// Orders the given <see cref="IEnumerable{T}"/> source using the given sorting options.
		/// </summary>
		/// <typeparam name="T">The type of the elements in <paramref name="source"/></typeparam>
		/// <param name="source">The data source</param>
		/// <param name="sortingOptions">The sorting options</param>
		/// <returns>The ordered result</returns>
		public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> source, SortingOptions sortingOptions)
		{
			return OrderBy<T>(source.AsQueryable<T>(), sortingOptions);
		}
	}
}
